package de.ret_world.eet.code;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;

/**
 * Represents a Alphabet of a number of Symbols used to create a CodeTable
 * @author Emu
 */
public class Alphabet {

    private final LinkedHashSet<Symbol> symbols;

    /**
     * Creates a new empty Alphabet. Add Symbols by calling the parseString() method.
     */
    public Alphabet() {
        symbols = new LinkedHashSet<Symbol>();
    }

    /**
     * Creates a new Alphabet.
     * <br><br>
     * This does the same as <i>new Alphabet().parseString(alph, seperator);</i>
     * @param alph A String representing the alphabet
     * @param seperator The String used in die Alphabet String to seperate the Symbols 
     */
    public Alphabet(String alph, String seperator) {
        this();
        parseString(alph, seperator);
    }

    /**
     * @return A Set of Symbols in the Alphabet
     */
    public LinkedHashSet<Symbol> getSymbols() {
        return symbols;
    }

    /**
     * Parses a String representing the Alphabet.
     * <br><br>
     * Example: a,b,c,d - "," is the seperating string
     * @param alph A String representing the alphabet
     * @param seperator The String used in die Alphabet String to seperate the Symbols 
     */
    public final void parseString(String alph, String seperator) {
        String[] symb = alph.split(seperator);
        int l = 0;
        for (String s : symb) {
            if (l > 0 && l != s.length()) {
                throw new IllegalArgumentException("All symbols in the alphabet have to be the same length.");
            } else {
                l = s.length();
            }
            symbols.add(new Symbol(s));
        }
    }

    /**
     * Creates a String representing the Alphabet with the given String as a seperator. This returns a String that can be parsed by another Alphabet to copy this one.
     * @param seperator The String used in die Alphabet String to seperate the Symbols 
     * @return The Alphabet String
     */
    public String getAlphabetString(String seperator) {
        StringBuilder result = new StringBuilder();

        for (Symbol s : symbols) {
            result.append(s).append(seperator);
        }
        return result.substring(0, result.length() - seperator.length());
    }

    /**
     * @return A shuffled List of all Symbols in the Alphabet
     */
    public List<Symbol> getShuffledAlphabet() {
        List<Symbol> list = new ArrayList<Symbol>(symbols);
        Collections.shuffle(list);
        return list;
    }

    /**
     * @return the number of symbols in the alphabet
     */
    public int getNumberOfSymbols() {
        return symbols.size();
    }

    @Override
    public String toString() {
        return symbols.toString();
    }

    /**
     * Use this method to check if an given password uses only symbols out of the alphabet
     * @param password the password to check
     * @return true if the password is ok, false if symbols are used that are not in the alphabet
     */
    public boolean checkPassword(String password) {
        if (password.length() % symbols.iterator().next().getLength() != 0) {
            return false;
        }
        if (!symbols.contains(new Symbol(password.substring(0, symbols.iterator().next().getLength())))) {
            return false;
        }

        return true;
    }
}
